﻿#include "eventserver.h"

EventSocket::EventSocket()
{
    m_peventserver = NULL;
}

void* EventSocket::getEventServer()
{
    return m_peventserver;
}

event& BaseEventServer::_getEventSocketReadEvent(EventSocket& AEventSocket)
{
    return AEventSocket.ev_read;
}

void BaseEventServer::_setEventServer(EventSocket& AEventSocket, void* AEventServer)
{
    AEventSocket.m_peventserver = AEventServer;
}

void* BaseEventServer::_getEventServer(EventSocket& AEventSocket)
{
    return AEventSocket.m_peventserver;
}

template<typename SOCKETSTRUCT, int NUM>
EventServer<SOCKETSTRUCT, NUM>::EventServer()
{
    m_listenSock = SOCKET_ERROR;
    m_bRun = false;
}

template<typename SOCKETSTRUCT, int NUM>
bool EventServer<SOCKETSTRUCT, NUM>::listen(int APort, int ABackNum)
{
    if(SOCKET_ERROR != m_listenSock)
    {
        return false;
    }

    m_listenSock = SocketApi::MakeListen(APort, ABackNum);
    if(SOCKET_ERROR != m_listenSock)
    {
        SocketApi::SetNonblock(m_listenSock);

        event_set(&m_listen_ev_read, m_listenSock, EV_READ | EV_PERSIST, S_OnAccept, this);
        event_add(&m_listen_ev_read, NULL);

        event_init();
        event_dispatch();
        return true;
    }
    else
    {
        return false;
    }
}

template<typename SOCKETSTRUCT, int NUM>
void EventServer<SOCKETSTRUCT, NUM>::_handlerNewClient()
{
    sock s = SOCKET_ERROR;
    struct sockaddr_in socketaddress;
    socklen_t size = sizeof(struct sockaddr);
    s = accept( m_listenSock, (struct sockaddr*)&socketaddress, &size);

    if (SOCKET_ERROR != s)
    {
        SOCKETSTRUCT* client = m_pool.getPtrElement();
        if(NULL != client)
        {
            _initBaseSocket(*client);
            _setBaseSocketSock(*client, s);
            SocketApi::SetNonblock(s);

            client->onConnection();

            _setEventServer(*client, this);

            event_set(&_getEventSocketReadEvent(*client), s, EV_READ|EV_PERSIST, S_OnReadData, client);
            event_add(&_getEventSocketReadEvent(*client), NULL);
        }
        else
        {
            cout << "not have resource, please close socket" << endl;
            SocketLib::SocketApi::CloseSocket(s);
        }
    }
}

template<typename SOCKETSTRUCT, int NUM>
bool EventServer<SOCKETSTRUCT, NUM>::_handlerClientRecv(SOCKETSTRUCT* client)
{
    bool isrecvok = client->recvData();
    if (isrecvok)
    {
        client->onRecved();
    }
    else
    {
        client->onClose();
        _disConnection(client);
    }

    return isrecvok;
}

template<typename SOCKETSTRUCT, int NUM>
bool EventServer<SOCKETSTRUCT, NUM>::poll(long AOverTime)
{
    if(!m_bRun)
        event_dispatch();
    m_bRun = true;

    return m_bRun;
}

template<typename SOCKETSTRUCT, int NUM>
void EventServer<SOCKETSTRUCT, NUM>::_disConnection(SOCKETSTRUCT* AClient)
{
    sock s = _getSock(*AClient);
    SocketLib::SocketApi::CloseSocket(s);
    m_pool.freePtrElement(AClient);
}

template<typename SOCKETSTRUCT, int NUM>
void EventServer<SOCKETSTRUCT, NUM>::disConnection(SOCKETSTRUCT* AClient)
{
    _disConnection(AClient);
}

template<typename SOCKETSTRUCT, int NUM>
static    void    S_OnAccept(int, short, void* arg)
{
    EventServer<SOCKETSTRUCT, NUM>*    pThis = (EventServer<SOCKETSTRUCT, NUM>*)arg;
    pThis->_handlerNewClient();
}

template<typename SOCKETSTRUCT, int NUM>
static    void    S_OnReadData(int, short, void* arg)
{
    SOCKETSTRUCT* client = (SOCKETSTRUCT*)arg;
    EventServer<SOCKETSTRUCT, NUM>*    pThis = (EventServer<SOCKETSTRUCT, NUM>*)client->getEventServer();
    pThis->_handlerClientRecv(client);
}
